package com.linxiao.call.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.linxiao.call.domain.CrmOutDeptPhoneNo;
import com.linxiao.call.mapper.CrmOutDeptPhoneNoMapper;
import com.linxiao.call.service.ICrmOutDeptPhoneNoService;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.RedisKeyConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.ConvertUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 外呼号码配置Service业务层处理
 *
 * @author zhoudong
 * @date 2022-05-17
 */
@Service
public class CrmOutDeptPhoneNoServiceImpl implements ICrmOutDeptPhoneNoService {
    @Resource
    private CrmOutDeptPhoneNoMapper crmOutDeptPhoneNoMapper;
    @Resource
    private ISysDeptService deptService;
    @Value("${show.outPhoneNo.timeout}")
    private int outPhoneNoTimeout;
    @Resource
    private RedisCache redisCache;

    /**
     * 查询外呼号码配置
     *
     * @param id 外呼号码配置主键
     * @return 外呼号码配置
     */
    @Override
    public CrmOutDeptPhoneNo selectCrmOutDeptPhoneNoById(Long id) {
        return crmOutDeptPhoneNoMapper.selectCrmOutDeptPhoneNoById(id);
    }

    /**
     * 查询外呼号码配置列表
     *
     * @param crmOutDeptPhoneNo 外呼号码配置
     * @return 外呼号码配置
     */
    @DataScope(deptAlias = "s")
    @Override
    public List<CrmOutDeptPhoneNo> selectCrmOutDeptPhoneNoList(CrmOutDeptPhoneNo crmOutDeptPhoneNo) {
        return crmOutDeptPhoneNoMapper.selectCrmOutDeptPhoneNoList(crmOutDeptPhoneNo);
    }

    /**
     * 新增外呼号码配置
     *
     * @param crmOutDeptPhoneNo 外呼号码配置
     * @return 结果
     */
    @Override
    public int insertCrmOutDeptPhoneNo(CrmOutDeptPhoneNo crmOutDeptPhoneNo) {
        // 1、检查部门下顺序是否存在
        CrmOutDeptPhoneNo dbCrmOutDeptPhoneNo = crmOutDeptPhoneNoMapper
                .selectOneByDeptIdAndSort(crmOutDeptPhoneNo.getDeptId(), crmOutDeptPhoneNo.getSort());

        if (dbCrmOutDeptPhoneNo != null) {
            throw new BaseException("当前商户下，排序" + crmOutDeptPhoneNo.getSort() + "已存在");
        }

        SysDept sysDept = deptService.selectDeptById(crmOutDeptPhoneNo.getDeptId());
        if (sysDept != null && StringUtils.isNotEmpty(sysDept.getAncestors())) {
            String[] split = sysDept.getAncestors().split(",");
            // 获取二级部门ID
            if (split.length > 2) {
                crmOutDeptPhoneNo.setMchId(ConvertUtil.Str2L(split[2]));
            } else {
                crmOutDeptPhoneNo.setMchId(crmOutDeptPhoneNo.getDeptId());
            }
        } else {
            return 0;
        }
        crmOutDeptPhoneNo.setCreateTime(DateUtils.getNowDate());
        crmOutDeptPhoneNo.setUpdateTime(DateUtils.getNowDate());
        crmOutDeptPhoneNo.setCreateBy(SecurityUtils.getUsername());
        int result = crmOutDeptPhoneNoMapper.insertCrmOutDeptPhoneNo(crmOutDeptPhoneNo);
        if(result > 0){
           this.clearRedisData(crmOutDeptPhoneNo.getDeptId());
        }
        return result;
    }

    /**
     * 清除redis 缓存数据
     * @param deptId
     */
    public void clearRedisData(long deptId){
        // 删除缓存
        String key = String.format(RedisKeyConstants.SHOW_OUT_PHONE_NO_DEPT, deptId);
        redisCache.redisTemplate.delete(key);
    }
    /**
     * 修改外呼号码配置
     *
     * @param crmOutDeptPhoneNo 外呼号码配置
     * @return 结果
     */
    @Override
    public int updateCrmOutDeptPhoneNo(CrmOutDeptPhoneNo crmOutDeptPhoneNo) {
        crmOutDeptPhoneNo.setUpdateTime(DateUtils.getNowDate());
        int result = crmOutDeptPhoneNoMapper.updateCrmOutDeptPhoneNo(crmOutDeptPhoneNo);
        if(result > 0){
            this.clearRedisData(crmOutDeptPhoneNo.getDeptId());
        }
        return result;
    }

    /**
     * 批量删除外呼号码配置
     *
     * @param ids 需要删除的外呼号码配置主键
     * @return 结果
     */
    @Override
    public int deleteCrmOutDeptPhoneNoByIds(Long[] ids) {
        List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos = new ArrayList<>();
        for(Long id :ids){
            CrmOutDeptPhoneNo crmOutDeptPhoneNo = crmOutDeptPhoneNoMapper.selectCrmOutDeptPhoneNoById(id);
            if(crmOutDeptPhoneNo != null){
                crmOutDeptPhoneNos.add(crmOutDeptPhoneNo);
            }
        }
        int result = crmOutDeptPhoneNoMapper.deleteCrmOutDeptPhoneNoByIds(ids);
        if(result > 0){
            crmOutDeptPhoneNos.stream().forEach(item ->{
                this.clearRedisData(item.getDeptId());
            });
        }
        return result;
    }

    /**
     * 删除外呼号码配置信息
     *
     * @param id 外呼号码配置主键
     * @return 结果
     */
    @Override
    public int deleteCrmOutDeptPhoneNoById(Long id) {
        CrmOutDeptPhoneNo crmOutDeptPhoneNo = crmOutDeptPhoneNoMapper.selectCrmOutDeptPhoneNoById(id);

        int result = crmOutDeptPhoneNoMapper.deleteCrmOutDeptPhoneNoById(id);
        if(result > 0){
            this.clearRedisData(crmOutDeptPhoneNo.getDeptId());
        }
        return result;
    }

    /**
     * 获取外显号码
     *
     * @param mobile
     * @return
     */
    @Override
    public CrmOutDeptPhoneNo selectShowPhoneNo(String mobile) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String key = String.format(RedisKeyConstants.SHOW_OUT_PHONE_NO_INDEX, loginUser.getUserId(), mobile);
        // 获取轮训下标
        long sort = redisCache.redisTemplate.opsForValue().increment(key);
        if (sort == 1L) {
            redisCache.expire(key, outPhoneNoTimeout, TimeUnit.MINUTES);
        }

        // 获取部门列表
        String ancestors = loginUser.getUser().getDept().getAncestors();
        if (StringUtils.isNotBlank(ancestors)) {
            String[] split = ancestors.split(",");
            List<String> list = Arrays.asList(split);
            List<String> deptIds = new ArrayList(list);
            deptIds.add(String.valueOf(loginUser.getDeptId()));
            for (int i = deptIds.size() - 1; i >= 0; i--) {
                List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos = selectByDeptId(Long.parseLong(deptIds.get(i)));
                if (CollectionUtil.isNotEmpty(crmOutDeptPhoneNos)) {
                    if (crmOutDeptPhoneNos.size() >= sort) {
                        return crmOutDeptPhoneNos.get((int) sort - 1);
                    } else {
                        redisCache.redisTemplate.opsForValue().set(key, "1");
                        return crmOutDeptPhoneNos.get(0);
                    }
                }
            }
        }
        return new CrmOutDeptPhoneNo();
    }

    /**
     * 清空轮训队列
     *
     * @param mobile
     * @return
     */
    @Override
    public String clearShowPhoneIndex(String mobile) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String key = String.format(RedisKeyConstants.SHOW_OUT_PHONE_NO_INDEX, loginUser.getUserId(), mobile);
        redisCache.redisTemplate.delete(key);
        return "Redis排队队列已清空";
    }



    /**
     * 获取对应部门的外显号码
     * @return
     *
     */
    @Override
    public AjaxResult getShowPhoneNoByDeptId() {
        LoginUser loginUser = SecurityUtils.getLoginUser();

        // 处理部门
        String ancestors = loginUser.getUser().getDept().getAncestors();
        List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos = new ArrayList<>();
        List<String> deptIds = new ArrayList<>();
        deptIds.add(String.valueOf(loginUser.getDeptId()));
        if (StringUtils.isNotBlank(ancestors)) {
            String[] split = ancestors.split(",");
            deptIds.addAll(Arrays.asList(split));
            for (String deptId : deptIds) {
                crmOutDeptPhoneNos.addAll(selectByDeptId(Long.parseLong(deptId)));
            }
        }

        // 按照外显号码去重
        List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos1 = crmOutDeptPhoneNos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CrmOutDeptPhoneNo::getShowPhoneNo))), ArrayList::new));
        // 从小到大
        List<CrmOutDeptPhoneNo> collect = crmOutDeptPhoneNos1.stream().sorted(Comparator.comparing(CrmOutDeptPhoneNo::getSort)).collect(Collectors.toList());
        return AjaxResult.success(collect);
    }


    /**
     * 根据部门ID，查询外显号码，有五分钟缓存
     *
     * @param deptId
     * @return
     */
    private List<CrmOutDeptPhoneNo> selectByDeptId(long deptId) {
        String key = String.format(RedisKeyConstants.SHOW_OUT_PHONE_NO_DEPT, deptId);

        Object result = redisCache.redisTemplate.opsForValue().get(key);
        if (result != null) {
            JSONArray results = JSON.parseArray(result.toString());
            List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos = new ArrayList<>();
            for (int i = 0; i < results.size(); i++) {
                crmOutDeptPhoneNos.add(JSON.to(CrmOutDeptPhoneNo.class, results.getJSONObject(i)));
            }
            return crmOutDeptPhoneNos;
        }
        List<CrmOutDeptPhoneNo> crmOutDeptPhoneNos = crmOutDeptPhoneNoMapper.selectByDeptId(deptId);
        if (CollectionUtil.isNotEmpty(crmOutDeptPhoneNos)) {
            redisCache.redisTemplate.opsForValue().set(key, JSON.toJSONString(crmOutDeptPhoneNos), 5, TimeUnit.MINUTES);
        }

        return crmOutDeptPhoneNos;
    }
}
